package com.ideaaedi.extspringcache.provider;


import com.ideaaedi.extspringcache.annotation.ExtCacheableOop;
import com.ideaaedi.extspringcache.parser.ExtCacheChecker;
import com.ideaaedi.extspringcache.redis.ExtRedisCacheManager;
import com.ideaaedi.extspringcache.support.SafeContainer;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.lang.Nullable;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * redis CacheManager provider, 用于管理所有的 ExtRedisCacheManager
 *
 * @author JustryDeng
 * @since 2020/11/8 12:22:26
 */
@Slf4j
@SuppressWarnings({"rawtypes", "SpringJavaInjectionPointsAutowiringInspection"})
public class ExtRedisCacheManagerProvider extends CommonRedisProvider implements CacheManagerProvider {
    
    public static final String BEAN_NAME = "extRedisCacheManagerProvider";
    
    @Autowired
    private ApplicationContext applicationContext;
    
    @Resource(name = ExtCacheChecker.BEAN_NAME)
    private ExtCacheChecker extCacheChecker;
    
    private final Map<ExtCacheableOop, ExtRedisCacheManager> redisCacheManagerMap = new ConcurrentHashMap<>(8);
    
    @Override
    @Nullable
    public CacheManager provide(ExtCacheableOop oop) {
        return redisCacheManagerMap.get(oop);
    }
    
    @Override
    public void afterSingletonsInstantiated() {
        // 初始化redisCacheManagerMap
        Map<String, RedisTemplate> tmpRedisTemplateMap = applicationContext.getBeansOfType(RedisTemplate.class);
        Set<String> redisTemplateNameSet = tmpRedisTemplateMap.keySet();
        SafeContainer.Data4Redis.redisTemplateNameAndOopMap().forEach((k, v) -> {
            Collection<ExtCacheableOop> oopCollection = SafeContainer.Data4Redis.redisTemplateNameAndOopMap().get(k);
            // 校验useTemplateName是否合法
            extCacheChecker.validRedisTemplateName(redisTemplateNameSet, k, oopCollection);
            RedisTemplate redisTemplate = tmpRedisTemplateMap.get(k);
            ExtRedisCacheManager extRedisCacheManager = getExtRedisCacheManager(redisTemplate);
            Iterator<ExtCacheableOop> iterator = oopCollection.stream().iterator();
            while (iterator.hasNext()) {
                redisCacheManagerMap.put(iterator.next(), extRedisCacheManager);
            }
        });
    }

}
